package com.zy.面向对象.特质

object Test {

  def main(args: Array[String]): Unit = {
    val student = new Student
    println(student.name)
    println(student.age)
    student.sayHello()
    student.play()


    println("==============================")

    val user = new RegisterUser("张三", "123456")
    user.insert()
  }

}

class Person {
  val name: String = "人类"
  val age: Int = 18

  def sayHello(): Unit = println(s"Person $name say hello")
}

// 使用trait声明特质
// 特质中属性的定义与抽象类相似，如果给初始值和方法体则为非抽象，如果没有初始值和方法体则为抽象
trait Yong {
  val name: String = "年轻"
  val age: Int

  def sayHello(): Unit = println(s"Yong person $name say hello")

  def play(): Unit
}

// 可以直接extends实现特质。或者使用extends继承父类，后使用with实现特质，可以使用多个with
class Student extends Person with Yong {

  // 因为父类和特质中都含有name且非抽象，所以必须要重写name
  override val name: String = "学生"

  // 父类中存在age属性，变相重写了Yong中的抽象属性age

  override def play(): Unit = println(s"student person $name is playing")


  override def sayHello(): Unit = {
    // super调用时，如果父类、特征有多个相同的方法，则按照从后向前的方式调用
    super.sayHello()

    // 可以在中括号中指定super实现类
    super[Person].sayHello()
  }

  // 存在菱形继承关系时 [A extends B]  [A extends C] [D extends B with C] 若都存在相同的方法，在调用时，顺序为 D -> C -> B -> A
}


class User(var name: String, var password: String)

trait UserDao {
  // 相当于引用了一个User对象，无需继承或者new
  _: User =>
  def insert(): Unit = println(s"insert into db user: ${this.name}")
}

class RegisterUser(user: String, password: String) extends User(user: String, password: String) with UserDao {

}
